package org.lts.yuqueexportor.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.lts.yuqueexportor.config.YuqueConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 文件服务
 */
@Slf4j
@Service
public class FileService {

    @Autowired
    private YuqueConfig yuqueConfig;

    @Autowired
    private CloseableHttpClient httpClient;

    /**
     * 从URL下载文件并保存到指定目录
     *
     * @param fileURL  文件下载URL
     * @param dirName  目录名称(知识库名称)
     * @return 是否下载成功
     */
    public boolean downloadAndSave(String fileURL, String dirName) {
        log.debug("开始下载文件: {}", fileURL);
        log.debug("目标目录: {}", dirName);

        int retryCount = 0;
        int maxRetries = yuqueConfig.getDownload().getRetryTimes();

        while (retryCount < maxRetries) {
            try {
                HttpGet httpGet = new HttpGet(fileURL);
                httpGet.setHeader("Cookie", yuqueConfig.getAuthToken());
                httpGet.setHeader("X-Csrf-Token", yuqueConfig.getCsrfToken());

                HttpResponse response = httpClient.execute(httpGet);
                int statusCode = response.getStatusLine().getStatusCode();
                log.debug("HTTP响应状态码: {}", statusCode);

                if (statusCode != 200) {
                    log.error("下载失败,HTTP状态码: {}, URL: {}", statusCode, fileURL);
                    return false;
                }

                HttpEntity entity = response.getEntity();

                if (entity == null) {
                    log.warn("下载失败,响应实体为空: {}", fileURL);
                    return false;
                }

                // 解析文件名
                String fileName = parseFileName(response);
                log.debug("解析的文件名: {}", fileName);

                if (fileName == null || fileName.isEmpty()) {
                    log.warn("无法解析文件名,使用默认文件名");
                    fileName = "未命名文档_" + System.currentTimeMillis() + ".md";
                }

                // 构建保存目录
                Path directory = Paths.get(yuqueConfig.getSavePath(), dirName);
                if (!Files.exists(directory)) {
                    Files.createDirectories(directory);
                    log.info("创建目录: {}", directory);
                }

                // 保存文件
                Path filePath = directory.resolve(fileName);
                try (InputStream inputStream = entity.getContent();
                     FileOutputStream outputStream = new FileOutputStream(filePath.toFile())) {

                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }

                log.info("文件下载成功: {}", filePath);
                return true;

            } catch (IOException e) {
                retryCount++;
                log.error("文件下载失败 (尝试 {}/{}): {}", retryCount, maxRetries, fileURL, e);

                if (retryCount < maxRetries) {
                    try {
                        Thread.sleep(yuqueConfig.getDownload().getRetryInterval());
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        log.error("重试等待被中断", ie);
                        return false;
                    }
                }
            }
        }

        log.error("文件下载失败,已达到最大重试次数: {}", fileURL);
        return false;
    }

    /**
     * 从HTTP响应中解析文件名
     */
    private String parseFileName(HttpResponse response) {
        try {
            if (response.getHeaders("Content-Disposition").length > 0) {
                String contentDisposition = response.getHeaders("Content-Disposition")[0].getValue();

                // 尝试解析 filename*=UTF-8''xxx 格式
                if (contentDisposition.contains("filename*=UTF-8''")) {
                    String encodedFileName = contentDisposition.split("filename\\*=UTF-8''")[1];
                    return URLDecoder.decode(encodedFileName, StandardCharsets.UTF_8);
                }

                // 尝试解析 filename="xxx" 格式
                if (contentDisposition.contains("filename=")) {
                    String fileName = contentDisposition.split("filename=")[1];
                    fileName = fileName.replaceAll("\"", "");
                    return URLDecoder.decode(fileName, StandardCharsets.UTF_8);
                }
            }
        } catch (Exception e) {
            log.warn("解析文件名失败", e);
        }

        return null;
    }

    /**
     * 直接保存Markdown内容到文件
     *
     * @param content  Markdown内容
     * @param fileName 文件名
     * @param dirName  目录名称(知识库名称)
     * @return 是否保存成功
     */
    public boolean saveMarkdownContent(String content, String fileName, String dirName) {
        try {
            // 确保文件名以.md结尾
            if (!fileName.endsWith(".md")) {
                fileName = fileName + ".md";
            }

            // 构建保存目录
            Path directory = Paths.get(yuqueConfig.getSavePath(), dirName);
            if (!Files.exists(directory)) {
                Files.createDirectories(directory);
                log.debug("创建目录: {}", directory);
            }

            // 保存文件
            Path filePath = directory.resolve(fileName);
            Files.writeString(filePath, content, StandardCharsets.UTF_8);

            log.info("Markdown文件保存成功: {}", filePath);
            return true;

        } catch (IOException e) {
            log.error("保存Markdown文件失败: {}/{}", dirName, fileName, e);
            return false;
        }
    }

    /**
     * 获取保存路径
     */
    public String getSavePath() {
        return yuqueConfig.getSavePath();
    }
}
